//手搓自定义展示表格
import {Message} from "element-ui";
export const LOG_LEVELS = ['debug', 'info', 'warn', 'error','pop']
export const LOG_LEVEL = 'debug';

export const log = (...opt)=>{
    // let {msg,type} = '';
    // if(opt.length > 1){
    //
    // }else{
    //
    // }
    type==='pop'? Message[type]() : console[type](msg)
}

export const infoNotify = (message, useHtml = false) => {
    if (useHtml) {
        Message.info({
            duration: 1000,
            dangerouslyUseHTMLString: true,
            message: message
        })
    } else {
        Message.info({
            duration: 1000,
            message: message
        })
    }
}

export class JsonSchema {
    constructor(schema) {
        //数据需要以list为蓝本，才能保证更新，树形数据无法检测深层对象
        schema || (schema = {});
        this.schema = typeof schema === 'string' ? schema : JSON.stringify(schema);
        this.json = JSON.parse(this.schema);
        this.list = [];
        this.map = new Map();
        this.init(this.json);
        console.log(this);
    }

    init(json = this.json, list = this.list, map = this.map) {
        const objToList = (obj, path) => {
            if (!obj) {
                infoNotify('格式错误');
                return list;
            } else if (typeof obj.type === 'string') {  //jsonschema对象
                Object.defineProperty(obj, 'path', {value: path, writable: true})
                // Object.defineProperty(obj, 'id', {value: JsonSchema.genId()})
                obj.id = JsonSchema.genId();
                list.push(obj);
                map.set(obj.id, obj);
                if (obj.type === 'object') {
                    Object.entries(obj.properties).forEach(([k, v]) => {
                        Object.defineProperty(v, 'parent', {value: obj})
                        objToList(v, path + '.' + k);
                    });
                } else if (obj.type === 'array') {
                    Object.defineProperty(obj.items, 'parent', {value: obj})
                    objToList(obj.items, path + '.items');
                }
            }
        }
        objToList(json, 'root', '')
        list.forEach(i => this.toSchemaObj(i))
        console.log(list);
        return {list, map};
    }

    toList(jsonschema) {
        const jsonList = [];
        const jsonMap = new Map();
        const objToList = (obj, path) => {
            if (!obj) {
                infoNotify('格式错误');
                return jsonList;
            } else if (typeof obj.type === 'string') {  //jsonschema对象
                let paths = path.split('.');
                jsonList.push({name: '    '.repeat(paths.length - 1) + paths.at(-1), ...obj});
                jsonMap.set(path, obj);
                if (obj.type === 'object') {
                    Object.entries(obj.properties).forEach(([k, v]) => {
                        objToList(v, path + '.' + k);
                    });
                } else if (obj.type === 'array') {
                    objToList(obj.items, path + '.items');
                }
            }
        }
        objToList(jsonschema, 'root', '')
        return jsonList;
    }

    static toTree(json) {
        if (!json) {
            return json;
        }
        json.id = Math.random()
        if ('type' in json && typeof json.type === 'string') {
            if ('properties' in json) {
                json.children = [...Object.values(json.properties)];
                Object.entries(json.properties).forEach(([k, v]) => {
                    v.name = k;
                    JsonSchema.toTree(v);
                });
            } else if ('items' in json) {
                json.items.name = 'items';
                json.children = [json.items];
                JsonSchema.toTree(json.items);
            }
        }
        return json;
    }

    //转为特殊对象
    toSchemaObj(json) {
        // Object.defineProperty(json, 'parent',{
        //     get: ()=> this.map.get(json.pid),
        //     set: (val)=> {
        //         json.path = val?.path + '.' + json.name;
        //     }
        // });
        Object.defineProperty(json, 'props', {
            get: () => {
                if (json?.items?.type === 'object') {
                    return json.items.properties;
                }
                return json.properties ?? json.items;
            },
        });
        Object.defineProperty(json, 'children', {
            get: () => {
                if (json?.items) return [json.items];
                else if (json?.properties) return [...Object.values(json.properties)];
                else return [];
            },
        });
        Object.defineProperty(json, 'name', { //root 和 items禁止修改
            get: () => json.path.split('.').at(-1),
            set: (val) => {
                if (Object.keys(json.parent.properties).includes(val)) {
                    infoNotify('属性名已存在');
                } else {
                    if (json.require) {
                        json.parent.required = json.parent?.required?.filter(i => i !== json.name).concat([val]);
                    }
                    Object.keys(json.parent.props).forEach(k => {
                        if (k === json.name) {  //排序
                            delete json.parent.properties[json.name]
                            json.path = json.parent?.path + '.' + val;
                            json.parent.props[val] = json
                        } else {
                            let temp = json.parent.props[k];
                            delete json.parent.props[k];
                            json.parent.props[k] = temp;
                        }
                    })
                }
            }
        });
        Object.defineProperty(json, '_type', {value: json.type, writable: true});
        Object.defineProperty(json, 'type', {
            enumerable: true,
            get: () => {
                return json._type;
            },
            set: (val) => {
                //修改类型将导致联动
                if (json._type !== val && ['object', 'array'].includes(json.type)) {
                    let key = '';
                    json._type === 'object' && (key = 'properties');
                    json._type === 'array' && (key = 'items');
                    (key in json) && delete json[key];
                    ('required' in json) && delete json['required'];
                    // 默认值及枚举类型变化暂时未处理，有需求再改
                }
                let old = json._type;
                json._type = val;
                if (old !== val && ['array'].includes(val)) {
                    this.addItems(json)
                }
            },
        });
        Object.defineProperty(json, 'require', {
            get: () => {
                if (json === this.json) {
                    return json?.required?.length === json?.children?.length;
                } else {
                    return json?.parent?.required?.includes(json.name);
                }
            },
            set: (v) => {
                if (json === this.json) {
                    if (v) {
                        json.required = Object.keys(json.properties);
                    } else {
                        json.required = [];
                    }
                } else {
                    if (v) {
                        if (!json.parent.required) {
                            json.parent.required = [json.name];
                        } else {
                            json.parent.required.push(json.name);
                        }
                    } else {
                        json.parent.required = json.parent?.required?.filter(i => i !== json.name);
                    }
                }
            }
        });
        // Object.defineProperty(json, '_view', {
        //     get: () => {
        //         return JsonSchema.toViewObj(json);
        //     },
        // });
    }

    static genId(len = 5) {
        return Math.random().toString(36).slice(2, len + 2);
    }

    // 使用 replacer 函数来排除 id 属性
    static replacer = (key, value) => {
        if (key === 'id') {
            return undefined;  // 不序列化 id 属性
        }
        return value;
    };

    add(row, asChild) {
        let id = JsonSchema.genId();
        let name = 'field_' + JsonSchema.genId();
        let newRow = {type: 'string'};
        let parent = asChild ? row : row.parent;
        Object.defineProperty(newRow, 'id', {value: id, enumerable: false})
        Object.defineProperty(newRow, 'path', {value: parent.path + '.' + name, writable: true})
        Object.defineProperty(newRow, 'parent', {value: parent})
        //只有object类型的父，array的为自动生成
        parent.properties ??= {};
        parent.properties[name] = newRow;
        this.toSchemaObj(newRow)
        //重定序
        this.sortProps(parent, newRow, row, false)
        return newRow;
    }

    addItems(row) {
        if (row.type !== 'array') {
            infoNotify('只有数组类型可以添加items')
            return;
        }
        let id = JsonSchema.genId();
        let newRow = {type: 'string'};
        Object.defineProperty(newRow, 'id', {value: id, enumerable: false})
        Object.defineProperty(newRow, 'path', {value: row.path + '.' + 'items', writable: true})
        Object.defineProperty(newRow, 'parent', {value: row})
        //只有object类型的父，array的为自动生成
        row.items = newRow;
        this.toSchemaObj(newRow)
        //重定序
        return newRow;
    }

    remove(row) {
        delete row.parent.properties[row.name];
        if (row.parent.required && row.parent.required.includes(row.name)) {
            if (row.parent.required.length === 1) {
                delete row.parent.required;
            } else {
                row.parent.required = row.parent?.required?.filter(i => i !== row.name);
            }
        }
    }

    //给属性进行写排序
    sortProps(parent, newObj, refObj, replace) {
        parent = parent.props;
        let keys = Object.keys(parent)
        // console.log("重排序前",Object.keys(parent))
        let refIndex = typeof refObj === 'object' ? keys.indexOf(refObj?.name) : refObj;
        //-1时不处理new,其他全都i>refIndex;
        keys.forEach((k, i) => {
            if (i === refIndex) {
                replace && delete parent[k];
                delete parent[newObj.name]
                parent[newObj.name] = newObj;
            } else if (i > refIndex && k !== newObj.name) {
                let temp = parent[k];
                delete parent[k];
                parent[k] = temp;
            }
        })
    }

    proxyObj = {
        set(target, prop, value, receiver) {
            if (!target.hasOwnProperty(prop)) { // 新属性
                console.log(`Adding new property: ${prop} with value: ${value}`);
            } else {                            // 已有属性
                console.log(`Updating property: ${prop} to value: ${value}`);
            }
            return Reflect.set(target, prop, value, receiver);
        },
        deleteProperty(target, prop) { // 删除属性
            return Reflect.deleteProperty(target, prop);
        }
    };

    //所有类型转字符串，有type反着来
    static convertView(val, type) {
        if (type) {
            let res = '';
            switch (type) {
                case 'string':
                    res = String(val);
                    break;
                case 'number':
                    res = parseFloat(val);
                    break;
                case 'integer':
                    res = parseInt(val);
                    break;
                case 'boolean':
                    res = Boolean(val);
                    break;
                case 'null':
                    res = null;
                    break;
                case 'array':
                    res = JSON.parse(val);
                    break
                case 'object':
                    res = JSON.parse(val);
                    break
                case 'json':
                    res = JSON.parse(val);
                    break
                default:
                    res = val.toString();
            }
            return res;
        } else {
            let res = '';
            // switch (typeof val){
            //     case 'string':
            //         res = String(val);break;
            //     case 'number':
            //         res = val.toString();break;
            //     case 'boolean':
            //         res = val.toString();break;
            //     case 'object':
            //         res = JSON.stringify(val);break
            //     default:
            //         res = val.toString();
            // }
            typeof val === 'object' && (res = JSON.stringify(val));
            return res;
        }
    }

    //响应式读写不一致对象
    static toViewObj(obj) {
        const view = {
            get: function (target, property, receiver) {
                if (property.endsWith('_view')) {
                    let val = Reflect.get(target, property.slice(0, -5), receiver);
                    return JsonSchema.convertView(val);
                }
                return Reflect.get(target, property, receiver);
            },
            set: function (target, property, value, receiver) {
                if (property.endsWith('_view')) {
                    let type =
                        typeof Reflect.get(target, property.slice(0, -5), receiver);
                    return Reflect.set(target, property, JsonSchema.convertView(value, type), receiver);
                }
                return Reflect.set(target, property, value, receiver);
            }
        };
        return new Proxy(obj, view);
    }

    static toEntries(obj) {
        let res = Object.entries(obj).filter(([key, value]) => value !== undefined);
        res.forEach(([k, v], i) => {
            res[i][2] = typeof v;
            if (res[i][2] === 'object') {
                res[i][1] = JsonSchema.convertView(res[i][1])
            }
        });
        return res;
    }

    static convertEntries(entries) {
        entries.forEach(([k, v, t], i) => {
            if (['object', 'array', 'null'].includes(t)) {
                try {
                    entries[i][1] = JsonSchema.convertView(entries[i][1], entries[i][2] ?? 'string');
                } catch (e) {
                    infoNotify(`类型转换失败请检查,源：${entries[i][1]},目标：${entries[i][2]}`)
                }
            }
        });
        return entries;
    }

    static getView(key) {
        let obj = JsonSchema.SCHEMA_KEYS[key];
        typeof key === "object" && (obj = key);
        let res = {data: obj}
        return Object.defineProperty(res, "view", {
            get() {
                console.log('出发取值', res)
                return JSON.stringify(res.data);
            },
            set(val) {
                try {
                    res.data = JSON.parse(val);
                } catch (e) {
                    infoNotify('请输入正确的json格式');
                }
            }
        })
    }

    //描述 JSON Schema 常用关键字及其约束类型，移除了较少用的和复杂的部分
    static SCHEMA_KEYS = {
        "STRING": {
            "type": "object",
            "properties": {
                "minLength": {
                    "type": "number",
                    "description": "字符串的最小长度"
                },
                "maxLength": {
                    "type": "number",
                    "description": "字符串的最大长度"
                },
                "pattern": {
                    "type": "string",
                    "description": "正则表达式，匹配字符串的模式"
                }
            },
            "description": "字符串类型的常用约束"
        },
        "NUMBER": {
            "type": "object",
            "properties": {
                // "multipleOf": {
                //     "type": "number",
                //     "description": "值必须是此数值的倍数"
                // },
                "minimum": {
                    "type": "number",
                    "description": "值的最小值"
                },
                "maximum": {
                    "type": "number",
                    "description": "值的最大值"
                },
                // "exclusiveMinimum": {
                //     "type": ["boolean", "number"],
                //     "description": "是否排除最小值"
                // },
                // "exclusiveMaximum": {
                //     "type": ["boolean", "number"],
                //     "description": "是否排除最大值"
                // }
            },
            "description": "数字类型的常用约束"
        },
        "BOOLEAN": {
            "type": "boolean",
            "description": "布尔类型，表示 true 或 false"
        },
        "OBJECT": {
            "type": "object",
            "properties": {
                "properties": {
                    "type": "object",
                    "description": "定义对象的属性及其类型",
                },
                // "additionalProperties": {
                //     "type": ["boolean", "object"],
                //     "description": "是否允许对象有额外的属性"
                // },
                "required": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "description": "定义对象中必须包含的属性",
                },
                // "minProperties": {
                //     "type": "number",
                //     "description": "对象最少必须有的属性数"
                // },
                // "maxProperties": {
                //     "type": "number",
                //     "description": "对象最多允许的属性数"
                // }
                "notEmpty": {
                    "type": "boolean",
                    "description": "是否不允许为空"
                }
            },
            "description": "对象类型的常用约束",
            "required": ["notEmpty"]
        },
        "ARRAY": {
            "type": "object",
            "properties": {
                "items": {
                    "type": "object",
                    "description": "数组中的元素类型定义",
                },
                "minItems": {
                    "type": "number",
                    "description": "数组最小元素数"
                },
                "maxItems": {
                    "type": "number",
                    "description": "数组最大元素数"
                },
                "uniqueItems": {
                    "type": "boolean",
                    "description": "数组中的元素是否要求唯一"
                }
            },
            "description": "数组类型的常用约束",
            "required": ["minItems","maxItems", "uniqueItems"]
        },
        "NULL": {
            "type": "null",
            "description": "空值类型"
        },
        "ANY": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "string",
                    "description": "自用的唯一标识"
                },
                "type": {
                    "type": "string",
                    "description": "任意数据类型的标识"
                },
                "title": {
                    "type": "string",
                    "description": "字段的标题"
                },
                "description": {
                    "type": "string",
                    "description": "字段的描述"
                },
                "default": {
                    "type": "any",
                    "description": "字段的默认值"
                },
                // "readOnly": {
                //     "type": "boolean",
                //     "description": "字段是否只读"
                // },
                // "writeOnly": {
                //     "type": "boolean",
                //     "description": "字段是否只写"
                // },
                "enum": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "description": "枚举值，允许的值列表"
                },
                "require": {
                    "type": "boolean",
                    "description": "（非标准自定义）该属性在上级中是否必须",
                },
            },
            "description": "适用于任意类型字段的通用约束"
        },
    }
}